import * as THREE from 'three'
import { stats } from '../stats'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

function createCourse30 (dom: HTMLElement) {
  const scene = new THREE.Scene()

  const camera = new THREE.PerspectiveCamera(75, dom.offsetWidth / dom.offsetHeight, 0.01, 1000)
  camera.position.set(20, 20, 20)

  const render = new THREE.WebGLRenderer()
  render.setSize(dom.offsetWidth, dom.offsetHeight)
  render.shadowMap.enabled = true

  dom.appendChild(render.domElement)

  const axes = new THREE.AxesHelper(100)
  scene.add(axes)

  camera.position.x = -20
  camera.position.y = 250
  camera.position.z = 100
  camera.lookAt(scene.position)
  scene.add(camera)

  const controls = new OrbitControls(camera, render.domElement)
  controls.update()

  createParticles('system1', 'https://dongli-three.oss-cn-shanghai.aliyuncs.com/snowflake1_t.png')
  createParticles('system2', 'https://dongli-three.oss-cn-shanghai.aliyuncs.com/snowflake2_t.png')
  createParticles('system3', 'https://dongli-three.oss-cn-shanghai.aliyuncs.com/snowflake3_t.png')
  createParticles('system4', 'https://dongli-three.oss-cn-shanghai.aliyuncs.com/snowflake4_t.png')

  function createParticles (name: string, strTexturePath: string) {
    const geom = new THREE.BufferGeometry()
    const material = new THREE.PointsMaterial({
      size: 10,
      transparent: true,
      opacity: 0.6,
      vertexColors: false,
      map: getTexture(strTexturePath),
      blending: THREE.AdditiveBlending,
      depthWrite: false,
      sizeAttenuation: true,
      color: new THREE.Color(0xffffff)
    })

    const positions = []
    const velocities = []

    const range = 400
    for (let i = 0; i < 15000; i++) {
      positions.push(Math.random() * range - range / 2,
        Math.random() * range * 1.5,
        Math.random() * range - range / 2)

      velocities.push((Math.random() - 0.5) / 3, 0.1 + Math.random() / 5, (Math.random() - 0.5) / 3)
    }

    geom.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3))
    geom.setAttribute('velocity', new THREE.Float32BufferAttribute(velocities, 3))

    const cloud = new THREE.Points(geom, material)
    cloud.name = name
    scene.add(cloud)
  }

  function getTexture (strPNGPath: string) {
    const texture = new THREE.TextureLoader().load(strPNGPath)
    return texture
  }

  render.setAnimationLoop(anmation)

  function anmation () {
    stats.update()

    scene.children.forEach(function (child) {
      if (child instanceof THREE.Points) {
        const cloud = child
        const posBufferAttr = cloud.geometry.getAttribute('position')
        const velBufferAttr = cloud.geometry.getAttribute('velocity')

        for (let i = 0; i < posBufferAttr.count; i++) {
          let posX = posBufferAttr.getX(i)
          let posY = posBufferAttr.getY(i)
          let posZ = posBufferAttr.getZ(i)

          let velX = velBufferAttr.getX(i)
          const velY = velBufferAttr.getY(i)
          let velZ = velBufferAttr.getZ(i)

          posX = posX - velX
          posY = posY - velY
          posZ = posZ - velZ

          if (posX <= -200 || posX >= 200) velX = velX * -1
          if (posY <= 0) posY = 600
          if (posZ <= -200 || posZ >= 200) velZ = velZ * -1

          posBufferAttr.setX(i, posX)
          posBufferAttr.setY(i, posY)
          posBufferAttr.setZ(i, posZ)

          velBufferAttr.setX(i, velX)
          velBufferAttr.setZ(i, velZ)
        }

        posBufferAttr.needsUpdate = true
        velBufferAttr.needsUpdate = true
      }
    })

    render.render(scene, camera)
  }

  return { camera, scene, render }
}

export {
  createCourse30
}
